#include "test.grpc.pb.h"
#include <iostream>
#include "test_client.hpp"
#include <asio/redirect_error.hpp>
#include <asio/steady_timer.hpp>




int main(int argc,char** argv)
{
    using namespace grpc;
    std::string server = "localhost:50051";
    auto channel = CreateChannel(server, InsecureChannelCredentials());
    asio::io_context io;
    auto& svc = asio::use_service<test_service>(io);
    auto& s2 = asio::use_service<test2_service>(io);
    auto& s3 = asio::use_service<test3_service>(io);
    
    s2.connect(channel);
    svc.connect(channel);
    s3.connect(channel);
    // auto& svc2 = asio::use_service<GrpcClientService<test2>>(io);
    // svc2.connect(channel);
    auto num = 100;
    if(argc > 1){
        num = std::stoi(argv[1]);
    }
    std::function<void()> do_process;
    std::function<void()> do_stream;
    do_stream = [&](){

        asio::co_spawn(io,[&]()->asio::awaitable<void>{
            try
            {
                std::cout<<"coroutine started!"<<std::endl;
                int_message req;
                auto [sender,reader] = co_await s3.stream_test();
                std::cout<<"connection started!"<<std::endl;
                for(int i=0;i<10;++i){
                    req.set_a(i);
                    co_await sender(req);
                }
                co_await sender({});
                std::cout<<"send finished!"<<std::endl;
                while(auto r = co_await reader()){
                    std::cout<<" stream input get "<<r->a()<<std::endl;
                }
                do_stream();
                // std::cout<<" call end"<<std::endl;
            }
            catch(const grpc::Status& e)
            {
                std::cerr<<"error! " << e.error_message()<< '\n';
            }
            
            co_return;
        },asio::detached);
    };
    do_process = [&](){
        // for(int i=0;i<6;++i)
        // {
            // asio::co_spawn(io,[&]()->asio::awaitable<void>{
            //     asio::steady_timer t(io);
            //     t.expires_after(std::chrono::milliseconds(50));
            //     asio::error_code c;
            //     co_await t.async_wait(asio::redirect_error(asio::use_awaitable,c));
            //     add_message req;
            //     req.set_a(1);
            //     req.set_b(12);
            //     auto res = co_await svc.fuck_add(req);
            //     std::cout<<"add result "<<res.a()<<std::endl;
            //     // if(i == 5){
            //         do_process();
            //     // }
            // },asio::detached);
            asio::co_spawn(io,[&io,&s2,&s3]()->asio::awaitable<void>{
                try{
                    int_message req;
                    req.set_a(1223);
                    auto [sender,result] = co_await s3.stream_param();
                    std::cout<<"connection success"<<std::endl;
                    co_await sender(req);
                    asio::steady_timer t(io);
                    t.expires_after(std::chrono::milliseconds(1000));
                    asio::error_code c;
                    co_await t.async_wait(asio::redirect_error(asio::use_awaitable,c));
                    co_await sender(req);
                    t.expires_after(std::chrono::milliseconds(1000));
                    co_await t.async_wait(asio::redirect_error(asio::use_awaitable,c));
                    co_await sender({});
                    std::cout<<"send finished"<<std::endl;
                    auto r = co_await result();

                }catch(grpc::Status& e){
                    std::cout<<e.error_code()<<" "<<e.error_message()<<std::endl;
                }
            },asio::detached);
        // }
    };
    do_process();
    // do_stream();
    io.run();
    return 0;
}